就是內建函式。
先列出常用的
之前提過,JavaScript 利用偽裝的行銷手法,所以他可以做到下面的事。JavaScript 弄的跟 Java 非常像,不只名稱連程式碼都是。
var s = new String( "Hello World!" );
console.log( s.toString() ); // "Hello World!"
可是實際上
typeof s; // "object" ... 不是 "String"
s instanceof String; // true
Object.prototype.toString.call(s); // "[object String]"
new String("Hello World!") 建立的字串包裹器的物件。裡面包著 "Hello World!",而不是建立純值(primitive)本身。
(嘗試著用一句話,引出整段的重點,方便閱讀。)
typeof 為 "object" 的值,會有額外內部 [[class]] 內建的特性。
[[class]]不是一般的類別,(這邊會用到原型 prototype 的概念)。請當做是在 Javascript 內部的分類項目,無法直接取用。
要透過 Object.prototype.toString(..)方法,以目標值呼叫來間接顯露。
這邊分為三個區塊
是否為純質(primitive),和是否為內建函式(natives)。
內部的 [[class]] 的值,會對應到關聯的內建原生建構器。
Object.prototype.toString.call( [1,2,3] );
// "[object Array]"
Object.prototype.toString.call( /regex-literal/i );
// "[object RegExp]"
雖然不存在 native,但還是會顯示出來了!
Object.prototype.toString.call( null );
// "[object Null]"
Object.prototype.toString.call( undefined );
// "[object Undefined]"
雖然顯示了,但背後有做很多事情。
Object.prototype.toString.call( "haha" );
// "[object String]"
Object.prototype.toString.call( 1208 );
// "[object Number]"
Object.prototype.toString.call( true );
// "[object Boolean]"
基本型別 ( primitives ) 都會自動被他們所對應的物件包裹器 ( object wrappers ) 所封裝 ( boxed ),這就是為何露出來的內部[[class]] 值分別會是 "String", "Number", 以及 "Boolean"了。
:::success
但成為了物件,JS引擎對顯示型別做了一些偽裝。
:::
基本型別沒有屬性或方法。(他怎麼做到下面的事情?)
var a = "haha";
a.length; // 4
a.toUpperCase; // "HAHA"
因為 JavaScript 自動幫你封裝了基本型別!以利這種存取。
(怎麼封的還沒提到,就是用到基本型別的物件包裹器。
這邊隱含著意思是,基本型別雖然不是物件,但有需要會幫你包一個方法。基本型別直接成為物件會降低效能。)
所以,既然他會幫你包,幫你最佳化。你就別再宣告 new String() 或 new Number() 再包一次。直接用字面值的基本型別。
var a = new Boolean( false );
if (!a) {
console.log( "Oops" ); // 永遠不會執行!
}
因為把 false 包裹起來,但物件是 truthy,當然不會執行。
手動封裝基本型別,還可以使用 Object(..) 函式。這和用 new 關鍵字完全相同。
var a = "abc";
var b = new String( a );
var c = Object( a );
現在想取出已封裝物件下的基本型別,兩種方法:valueOf()、隱性強制轉型。
var a = new String( "abc" );
a.valueof(); // "abc"
借用這個方法,可以把型別從物件轉回來。
var a = new String( "abc" );
var b = a + ""; // b
typeof a; // "object"
typeof b; // "string"